Skip to content

Conversation

@stephanieyzhang
Copy link

@stephanieyzhang stephanieyzhang commented Sep 12, 2025

PlainTextRange is a specialized, live AbstractRange subclass for the value space of <input>/<textarea> and other elements whose specifications define that they support plain text ranges. It enables range-based operations in the element's logical value while restricting standard Range mutations to preserve encapsulation. It integrates cleanly with existing selection/editing behavior and closes a long-standing gap.

(See WHATWG Working Mode: Changes for more details.)


Preview | Diff

@stephanieyzhang stephanieyzhang changed the title initial changes Add FormControlRange interface Sep 23, 2025
Copy link
Contributor

@dandclark dandclark left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great to see a spec for this coming together!

@rniwa
Copy link
Collaborator

rniwa commented Sep 29, 2025

FWIW, I'd rather extend Range so that it can work with shadow host in general instead of creating a new interface specifically for form controls.

@stephanieyzhang
Copy link
Author

FWIW, I'd rather extend Range so that it can work with shadow host in general instead of creating a new interface specifically for form controls.

We explored extending Range, including shadow host support, but found compatibility and encapsulation issues that made it risky to change existing Range semantics. Based on feedback across discussions, we went with a dedicated FormControlRange instead. The trade-offs and alternatives are covered in the explainer.

@rniwa
Copy link
Collaborator

rniwa commented Sep 30, 2025

FWIW, I'd rather extend Range so that it can work with shadow host in general instead of creating a new interface specifically for form controls.

We explored extending Range, including shadow host support, but found compatibility and encapsulation issues that made it risky to change existing Range semantics. Based on feedback across discussions, we went with a dedicated FormControlRange instead. The trade-offs and alternatives are covered in the explainer.

Changing the behavior of setStart/setEnd wouldn't be an only way to solve this problem. I'd instead add a new argument or a new function which specifies "offset" within element's shadow tree.

Copy link
Contributor

@dandclark dandclark left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is looking good! Next big steps will be defining the right integration points from the HTML spec, and working towards consensus on the API shape.

dom.bs Outdated
<a>this</a>'s <a for=FormControlRange>end offset</a> to <var>endOffset</var>.
</ol>

<p>If an {{HTMLInputElement}}'s <code>type</code> changes to a type that does not
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(this, too, will likely need to be something that we'll need to put in the HTML spec)

@dandclark
Copy link
Contributor

Changing the behavior of setStart/setEnd wouldn't be an only way to solve this problem. I'd instead add a new argument or a new function which specifies "offset" within element's shadow tree.

@rniwa Thanks for the feedback! Yeah, there are a lot of ways this could be done. This suggestion sounds closer to the 2nd considered approach here. There are enough differences in how a Range inside a builtin element would work vs a "normal" range that we believe it will be overall cleaner and less confusing to split the functionality into a different type. For example the behavior we propose here is that a FormControlRange can't have one boundary point inside a <textarea>/<input> and another boundary point outside, which would be a clumsier invariant to express with the Range API surface. Adding this to Range would also add confusion about what things like Range.selectNodeContents should do; should it move the range to select an <input>'s value string, or not? We could add a parameter to all the setter functions to switch the behavior, but again it seems cleaner to relegate the behavior to a different interface vs adding parameters to a bunch of Range functions.

Anyway, whatwg/html#11478 is a better place to have this discussion -- more folks are following that issue vs this draft PR. @stephanieyzhang it might be helpful if you could update the PR description for this to point to that issue, as well as a direct link to the explainer.

@stephanieyzhang stephanieyzhang changed the title Add FormControlRange interface Add PlainTextRange interface Dec 4, 2025

<pre class=idl>
[Exposed=Window]
interface PlainTextRange : AbstractRange {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is the wrong name now the idea is to no longer tie it to text.


<ul>
<li><p><dfn export for=PlainTextRange id=plaintext-range-host>host</dfn> (null or an
{{Element}}).</p></li>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need this? The host should be in charge of allocating these at which point these don't really need to have a host owner.

</ul>

<p>The {{AbstractRange/startContainer}} getter steps for {{PlainTextRange}} objects are to return
null.</p>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't work. You need to adjust AbstractRange getter (including IDL) to allow for returning null here. And we do still want to store the actual start/end container so AbstractRange will need to support some kind of "is opaque" switch.

updated using the rules above.</p>

<p>The <dfn export for=PlainTextRange id=dom-plaintext-range-stringifier>stringification
behavior</dfn> must run these steps:</p>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As I mentioned in whatwg/html#11478 (comment) I don't think exposing toString() is correct at this level.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

4 participants